Fix five GitHub issues: string coercion, parameter shadowing, operators, scope, typing - #587
Conversation
…567) - #583: stop coercing the Text value "[]" to an empty List in the VariableDeclaration handler; a quoted string keeps its Text type. - #582: bind action/event parameters with define_direct so a parameter shadows a same-named global instead of the global overriding the arg. - #566: add KeywordStarts/KeywordEnds tokens and an infix parse desugaring `X starts with Y` / `X ends with Y` to the starts_with/ends_with builtins, so they work end-to-end (not just under --analyze); update route arms. - #557: skip native builtins in extract_parent_variables so an included file can use date-unit words (year/month/day/hour/minute/second) as action-local variables, matching main-file behavior (non-fatal). - #567: accept Any/Unknown in the add/split/binary-arithmetic typechecker rules and stop erroring on untyped-parameter references (gradual typing). Adds tests/github_issues_batch_test.rs (13 regression tests). All existing TestPrograms continue to pass. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HYUZcFy2vaiKcT9YzxVZYo
|
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
|
Warning Review limit reached
Next review available in: 1 minute Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please refer docs for additional details. Review details⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (2)
📝 WalkthroughWalkthroughThis PR fixes five GitHub issues: prevents "[]" text from being coerced to an empty list, changes parameter binding to use define_direct so parameters shadow globals, adds "starts with"/"ends with" operator parsing, excludes native functions from parent-variable extraction to fix include-file scoping conflicts, and relaxes typechecker rules for Any/Unknown types. Includes regression tests and a dev diary entry. ChangesGitHub issues batch fix
Estimated code review effort: 3 (Moderate) | ~25 minutes Sequence Diagram(s)sequenceDiagram
participant Caller
participant Interpreter
participant Scope
Caller->>Interpreter: invoke action/event with parameters
Interpreter->>Scope: define_direct(parameter, value)
Scope-->>Interpreter: parameter binding shadows outer/global
Interpreter-->>Caller: execute body with shadowed parameter
Possibly related PRs
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
src/typechecker/mod.rs (1)
1552-1570: 🎯 Functional Correctness | 🔴 Critical | ⚡ Quick winList element check still rejects adding concrete values — contradicts stated fix.
The guard only checks
value_type != Type::Any, but never checks whether the list's own element type isAny. For a variable typedList(Any)(the common return type ofpush,filter,map,parse_json, etc.), adding e.g. aNumberstill trips this condition:
**element_type != Type::Unknown→ true (it'sAny)**element_type != value_type→ true (Any != Number)value_type != Type::Unknown→ truevalue_type != Type::Any→ true (Number)All four are true, so
type_errorfires — a false positive that the line-range summary explicitly claims is fixed ("allows adding values to lists when the list element type isAny").🐛 Proposed fix
match &symbol.symbol_type { Some(Type::List(element_type)) => { if **element_type != Type::Unknown + && **element_type != Type::Any && **element_type != value_type && value_type != Type::Unknown && value_type != Type::Any {🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/typechecker/mod.rs` around lines 1552 - 1570, The list element compatibility check in the typechecker still rejects valid writes to List(Any) values. Update the logic in the list-addition branch inside the type checking path so the `type_error` guard also treats the list’s own `element_type` of `Type::Any` as permissive, alongside the existing `Type::Unknown` handling. Make the fix in the `self.analyzer.get_symbol(list_name)` / `Type::List(element_type)` match so concrete `value_type`s are accepted when the list is typed as `Any`.
🧹 Nitpick comments (1)
src/typechecker/mod.rs (1)
1588-1600: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win
_catch-all forAddToListStatementdoesn't treatAny-typed variables permissively.If
list_name's symbol type isAny(statically unknown, could be a list at runtime), this arm still raises "Cannot add to non-list variable" since onlySome(Type::Unknown)is excluded. For consistency with the gradual-typing intent applied elsewhere in this PR,Anyshould likely be treated the same asUnknownhere.♻️ Proposed fix
_ => { // Variable might not be a list - if symbol.symbol_type != Some(Type::Unknown) { + if symbol.symbol_type != Some(Type::Unknown) + && symbol.symbol_type != Some(Type::Any) + { self.type_error(🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/typechecker/mod.rs` around lines 1588 - 1600, In the AddToListStatement handling inside typechecker::mod::TypeChecker, the catch-all arm currently rejects variables typed as Any even though they should be treated permissively like Unknown. Update the conditional around self.type_error so that symbol.symbol_type == Some(Type::Any) is also excluded alongside Type::Unknown, keeping the existing behavior for definite non-list types while allowing gradual-typing cases to pass.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@tests/github_issues_batch_test.rs`:
- Around line 22-46: The test helper currently hardcodes the WFL executable path
in wfl_exe(), which can break under cargo test and may use a stale build. Update
wfl_exe() to return the Cargo-provided binary path via
env!("CARGO_BIN_EXE_wfl"), and keep run_src() using that helper so the tests
always invoke the exact test-built binary regardless of working directory or
build mode.
---
Outside diff comments:
In `@src/typechecker/mod.rs`:
- Around line 1552-1570: The list element compatibility check in the typechecker
still rejects valid writes to List(Any) values. Update the logic in the
list-addition branch inside the type checking path so the `type_error` guard
also treats the list’s own `element_type` of `Type::Any` as permissive,
alongside the existing `Type::Unknown` handling. Make the fix in the
`self.analyzer.get_symbol(list_name)` / `Type::List(element_type)` match so
concrete `value_type`s are accepted when the list is typed as `Any`.
---
Nitpick comments:
In `@src/typechecker/mod.rs`:
- Around line 1588-1600: In the AddToListStatement handling inside
typechecker::mod::TypeChecker, the catch-all arm currently rejects variables
typed as Any even though they should be treated permissively like Unknown.
Update the conditional around self.type_error so that symbol.symbol_type ==
Some(Type::Any) is also excluded alongside Type::Unknown, keeping the existing
behavior for definite non-list types while allowing gradual-typing cases to
pass.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 6a6a8bc6-7a9c-4407-9ac9-18f87778ac31
📒 Files selected for processing (7)
Dev diary/2026-07-06-github-issues-batch-583-582-566-557-567.mdsrc/interpreter/mod.rssrc/lexer/token.rssrc/parser/expr/binary.rssrc/parser/stmt/route.rssrc/typechecker/mod.rstests/github_issues_batch_test.rs
Address CodeRabbit review on PR #587: the batch test helper hardcoded `target/release/wfl`, which is working-directory dependent and can pick up a stale or missing build. Use Cargo's `env!("CARGO_BIN_EXE_wfl")`, which resolves to the exact binary built for this integration-test run in any profile. Verified: all 13 tests pass under plain `cargo test` (debug). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HYUZcFy2vaiKcT9YzxVZYo
|
Verify each finding against current code. Fix only still-valid issues, skip the In |
Follow-up to the #567 gradual-typing relaxation: the `add X to <list>` rule still rejected adding a concrete value to a list whose element type is `Any` (e.g. a `[1, 2]` literal, typed `List(Any)`), emitting a false "Cannot add Text to list of Any". Treat an `Any` element type as permissive alongside the existing `Unknown` handling — a list of statically-unknown element type accepts any value. Adds a regression test. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HYUZcFy2vaiKcT9YzxVZYo
|
Verified and fixed in The finding was still valid: the Repro now runs clean (no type warning, exit 0): Added a regression test ( Note: the only red check, Generated by Claude Code |
Summary
This PR fixes five distinct bugs discovered in an open-issues review, all verified against a fresh release build:
"[]"strings were incorrectly coerced to empty listsends with/starts withoperators are swallowed as multi-word identifiers at statement level #566:starts with/ends withoperators were swallowed as multi-word identifiersAny/Unknownvalues were rejected by type-checker rules (gradual typing)Key Changes
#583 — String coercion removed
VariableDeclarationthat converted anyTextvalue equal to"[]"into an emptyList#582 — Parameter shadowing fixed
define()(rejects outer-scope names) todefine_direct()(current-scope only)call_function) and event-handler parameters#566 —
starts with/ends withoperators addedKeywordStartsandKeywordEndstokens (contextual, usable as identifiers elsewhere)binary.rsat comparison precedence that desugars to existingstarts_with/ends_withbuiltinsrouteconstruct'swhen starts with/when ends witharms to use new tokens#557 — Include-file scope handling fixed
extract_parent_variablesto skipValue::NativeFunctionentriesis_builtin_function, so seeding them as shadowable variables only made includes stricter#567 — Gradual typing for
Any/Unknownvaluesadd X to <number>andadd X to <list>now acceptAny/UnknownoperandsAnyoperands degrades gracefully (comparisons yieldBoolean,PluswithTextyieldsText, others yieldAny)split X by YacceptsAny/Unknownfor both operandsUnknownsilently instead of raising a false type errorTesting
Added
tests/github_issues_batch_test.rswith 13 regression tests covering:"[]"stringsstarts/ends withpositive/negative cases and stored boolean resultsAny/Unknownflowing intoadd, arithmetic, andsplitoperationsAll existing
TestProgramscontinue to pass (no regressions).https://claude.ai/code/session_01HYUZcFy2vaiKcT9YzxVZYo
Summary by CodeRabbit
[]stays as text instead of being converted unexpectedly.starts withandends within expressions and route conditions.